package com.gmail.dengtao.joe.game.server.group;

import java.util.Iterator;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gmail.dengtao.joe.commons.util.NumberUtils;
import com.gmail.dengtao.joe.game.model.Player;
import com.gmail.dengtao.joe.game.server.Constant;
import com.gmail.dengtao.joe.game.server.GameCache;
import com.gmail.dengtao.joe.game.server.client.handler.GameClientHandler;
import com.gmail.dengtao.joe.group.channel.Channel;
import com.gmail.dengtao.joe.group.channel.ChannelListener;
import com.gmail.dengtao.joe.group.member.IdleStatus;
import com.gmail.dengtao.joe.group.member.Member;
import com.gmail.dengtao.joe.group.member.MembershipListener;
import com.gmail.dengtao.joe.transport.session.Session;

public class ServerGroupListener implements MembershipListener, ChannelListener {

	private static final Logger LOGGER = LoggerFactory.getLogger(ServerGroupListener.class);
	
	private GameClientHandler handler;
	
	@Override
	public void dataReceived(Channel channel, Member sender, Object data) throws Exception {
		String message = new String((byte[]) data);
		LOGGER.info("[CHANNEL][R][" + message + "][SOURCES:" + sender + "]");
		String[] params = message.split("\\|");
		if (Constant.NOTIFY_PLAYER_LOGIN.equals(params[0])) {	// player login
			Player player = new Player();
			player.setName(params[1]);
			player.setShape(NumberUtils.toInt(params[2]));
			player.setColor(params[3]);
			player.setX(NumberUtils.toInt(params[4]));
			player.setY(NumberUtils.toInt(params[5]));
			// 通知下线
			Session player_session = GameCache.sessions.get(player);
			if (player_session != null) {
				LOGGER.info("[CHANNEL][PLAYER LOGIN ANOTHER SERVER][" + player.getName() + "][LOGOFF]");
				player_session.send(handler.packetData(Constant.CLIENT_PLAYER_LOGIN_OFF, ""));
				GameCache.playersCache.remove(player_session);
			}
			GameCache.remotePlayers.put(player.getName(), player);
			broadcast(Constant.NOTIFY_PLAYER_LOGIN, player.getName() + "|" + player.getShape() + "|" + player.getColor() + "|" + player.getX() + "|" + player.getY());
		} else if (Constant.NOTIFY_PLAYER_LOGOFF.equals(params[0])) {	// player logoff
			Player player = GameCache.remotePlayers.get(params[1]);
			if (player != null) {
				GameCache.remotePlayers.remove(player.getName());
				broadcast(Constant.NOTIFY_PLAYER_LOGOFF, player.getName());
			}
		} else if (Constant.NOTIFY_PLAYER_MOVE.equals(params[0])) {	// player move
			Player player = null;
			if (GameCache.remotePlayers.containsKey(params[1])) {
				player = GameCache.remotePlayers.get(params[1]);
			} else {
				player = new Player();
				player.setName(params[1]);
				GameCache.remotePlayers.put(params[1], player);
			}
			player.setShape(NumberUtils.toInt(params[2]));
			player.setColor(params[3]);
			player.setX(NumberUtils.toInt(params[4]));
			player.setY(NumberUtils.toInt(params[5]));
			broadcast(Constant.NOTIFY_PLAYER_MOVE, player.getName() + "|" + player.getShape() + "|" + player.getColor() + "|" + player.getX() + "|" + player.getY());
		}
	}

	@Override
	public void dataSent(Channel channel, Member target, Object data) throws Exception {
		LOGGER.info("[CHANNEL][S][" + data + "][TARGET:" + target + "]");
	}

	@Override
	public void dataNotSent(Channel channel, Member target, Object data) throws Exception {
		LOGGER.info("[CHANNEL][NS][" + data + "][TARGET:" + target + "]");
	}
	
	@Override
	public void exceptionCaught(Channel channel, Member source, Throwable cause) {
		cause.printStackTrace();
	}

	@Override
	public void memberAdded(Channel channel, Member member) throws Exception {
		LOGGER.info("[CHANNEL][NEW SERVER:" + member + "]");
		pushLocalPlayers(channel, member);	// Push local members
	}

	@Override
	public void memberIdle(Channel channel, Member member, IdleStatus status) throws Exception {
		LOGGER.info("[CHANNEL][SERVER IDLE:" + member + "]");
	}

	@Override
	public void memberDisappeared(Channel channel, Member member) throws Exception {
		LOGGER.warn("[CHANNEL][LOSE SERVER:" + member + "]");
	}
	
	// 广播到客户端
	private void broadcast(String type, String data) {
		if (handler != null) {
			handler.broadcast(null, handler.packetData(type, data));
		}
	}

	public void setHandler(GameClientHandler handler) {
		this.handler = handler;
	}
	
	// 推送当前玩家列表
	private void pushLocalPlayers(Channel channel, Member target) {
		Iterator<Entry<String, Player>> iter = GameCache.players.entrySet().iterator();
		for ( ; iter.hasNext(); ) {
			Entry<String, Player> entry = iter.next();
			Player player = entry.getValue();
			channel.send(target, Constant.NOTIFY_PLAYER_LOGIN + "|" + player.getName() + "|" + player.getShape() + "|" + player.getColor() + "|" + player.getX() + "|" + player.getY());
		}
	}

}
